/*

Âmbito:		Mestrado em Engenharia de Segurança Informática

Local:		Instituto Politécnico de Beja
		Escola Superior de Tecnologia e Gestão 

Título:		Gerador de Números Pseudo-Aleatorios

Descrição: 	O trabalho consiste na programação do algoritmo de geração de números pseudo-aleatórios
		inteiros positivos de 16-bit.

Docente:	José Jasnau Caeiro

Realizado por:	Ivã Marinheiro Nº12050
		Manuel Coelho Nº12057
		Fevereiro 2012
				
*/
 
 
//importação das bibliotecas necessárias à execução do programa
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <string.h>


//declaração da Tabela T como variável global
int T[1000];
//declaração das variáveis para medir o tempo como globais
int t1, t2;



/*
Declaração das Funções do Programa
*/
void initrand();
int preencher_tabela();
int aleatorio_p();
void permutaT(int l);
int novo_valor_p(int z1, int z2, int z3, int z4);


 
 
/*
Função main
------> início da exceução do programa <------
*/
int main(int argc, char* argv[])
{

	int p, l, z1, z2, z3, z4, N, novo_p, t1, t2, n_ite, n_iteracoes, contador;
	p=0, l=0, z1=0, z2=0, z3=0, z4=0, N=0, novo_p=0, t1=0, t2=0, n_ite=0, n_iteracoes=0, contador=0;
	
	//para medir o tempo de execução do programa
	t1 = clock();
	
	//número de iterações introduzido directamente no código, para apenas medirmos os tempos
	n_ite = 10000000;
	
	//chamada a função para limpar o clock, de modo a dar sempre um aleatório diferente sem problemas
        initrand();
        
        //chama a função que preencha a Tabela T
        preencher_tabela();
        
        //chama a função que devolve um número aleatório entre 0 e 999
        p = aleatorio_p();
        
        
        //ciclo que vai gerar o número de iterações introduzido pelo utilizador
        while (contador < n_ite)
        {
       		
		//assigna-se à variável z1 o elemento Tl , com l = p, se p < 1000 e l = 0 se p ≥ 1000
		if (p < 1000)
		{
			l = p;
			z1 = T[l];
		}
		if (p >= 1000)
		{
			l = 0;
			z1 = T[l];
		}

		permutaT(l);
		
		
		//assigna-se à variável z2 o elemento Tl , com l = p+1, se p < 999 e l = 0 se p ≥ 999 ;
		if (p < 999)
		{
			l = p + 1;
			z2 = T[l];
		}
		if (p >= 999)
		{
			l = 0;
			z2 = T[l];
		}

		permutaT(l);
		
		
		//assigna-se à variável z3 o elemento Tl , com l = p+2, se p < 998 e l = 0 se p ≥ 998
		if (p < 998)
		{
			l = p + 2;
			z3 = T[l];
		}
		if (p >= 998)
		{
			l = 0;
			z3 = T[l];
		}

		permutaT(l);
		
		
		//assigna-se à variável z4 o elemento Tl , com l = p+3, se p < 997 e l = 0 se p ≥ 997
		if (p < 997)
		{
			l = p + 3;
			z4 = T[l];
		}
		if (p >= 997)
		{
			l = 0;
			z4 = T[l];
		}

		permutaT(l);
		
		
		//acção-> Nk = z1 << 12 || z2 << 8 || z3 << 4 || z4
		N = z1 << 12 | z2 << 8 | z3 << 4 | z4;

		
		//acção-> p = z1 × 102 + z2 × 101 + z3 × 10
		novo_p = novo_valor_p(z1, z2, z3, z4);
		p = novo_p;  
	
		contador ++;
	
	}
	
	//para medir o tempo de execução do programa
	t2 = clock();
	
        
	return 0;
}
/*
------------------------------------------------------------------------------
*/
 
 
/*
Função para limpar o clock, e gerar sempre números aleatórios diferentes
*/
void initrand() 
{ 
    srand((unsigned)(time(0))); 
} 



/* 
Cia uma Tabela T com 1000 elementos entre 0 e 9 em igual numero
*/
int preencher_tabela()
{
	int i, num, controlo, contador, controlo_0, controlo_1, controlo_2, controlo_3, controlo_4, controlo_5, controlo_6, controlo_7, controlo_8, controlo_9;
	
	i=0;
	num=0;
	controlo=0;
	controlo_0=0, controlo_1=0, controlo_2=0, controlo_3=0, controlo_4=0, controlo_5=0, controlo_6=0, controlo_7=0, controlo_8=0, controlo_9=0;
	contador=0;

	//inicializa a Tabela T a zeros
	for(i=0 ; i<1000 ; i++)
	{
		T[i] = 0;
		//printf("T - %d\n", T[i]);
	}
	
	while (contador < 1000)
        {
	        num = (rand() % 10);
	        //printf("  %d", num);	        
	        
	        if (num == 0 && controlo_0 < 100)
	        {	   	
			controlo_0 ++;
                	T[contador] = num;	        
	        }
	       
	        if (num == 1 && controlo_1 < 100)
	        {	   	
			controlo_1 ++;
                	T[contador] = num;	        
	        }
	        if (num == 2 && controlo_2 < 100)
	        {	   	
			controlo_2 ++;
                	T[contador] = num;	        
	        }
	        if (num == 3 && controlo_3 < 100)
	        {	   	
			controlo_3 ++;
                	T[contador] = num;	        
	        }	
	        if (num == 4 && controlo_4 < 100)
	        {	   	
			controlo_4 ++;
                	T[contador] = num;	        
	        }
	        if (num == 5 && controlo_5 < 100)
	        {	   	
			controlo_5 ++;
                	T[contador] = num;	        
	        }	
	        if (num == 6 && controlo_6 < 100)
	        {	   	
			controlo_6 ++;
                	T[contador] = num;	        
	        }
	        if (num == 7 && controlo_7 < 100)
	        {	   	
			controlo_7 ++;
                	T[contador] = num;	        
	        }
	        if (num == 8 && controlo_8 < 100)
	        {	   	
			controlo_8 ++;
                	T[contador] = num;	        
	        }
	        if (num == 9 && controlo_9 < 100)
	        {	   	
			controlo_9 ++;
                	T[contador] = num;	        
	        }
     
	        contador++;
        
        }   
        

}


/*
Função que devolve um número aleatório entre 0 e 999 
*/
int aleatorio_p()
{
	int num;
	num = 0;
	
	//primeiro limpa o clock, com a chamada a esta função
	srand((unsigned)(time(0))); 
	num = (rand() % 999);
	return num;
}


/*
Função que permuta o valor em T[l] com o valor em T[0]
*/
void permutaT(int l) 
{
	int aux;
	aux = 0;
	
	aux = T[l];
	T[l] = T[0];
	T[0] = aux;
}


/*
Função que gera o novo valor de p
*/
int novo_valor_p(int z1, int z2, int z3, int z4)
{	
	return (z1 * 100) + (z2 * 10) + (z3 * 1);
}	





